package codegen.config.validator;

import codegen.config.Configuration;
import codegen.config.exception.ConfigurationException;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 配置验证器
 * 用于验证配置文件的有效性，确保所有必要的配置项都存在且有效。
 * 验证内容包括：
 * 1. 项目基本信息的完整性
 * 2. 代码生成配置的有效性
 * 3. 数据库连接配置的正确性
 * 4. 模板配置的完整性
 *
 * @author codegen
 * @since 1.0.0
 */
public class ConfigValidator {

    /**
     * 验证配置的有效性
     * 该方法会验证整个配置对象的所有必要字段，确保配置的完整性和正确性。
     * 如果发现任何错误，会收集所有错误信息，然后一次性抛出异常。
     *
     * @param config 要验证的配置对象
     * @throws ConfigurationException 当配置验证失败时抛出，异常信息包含所有验证错误的详细说明
     */
    public static void validate(Configuration config) {
        List<String> errors = new ArrayList<>();

        // 验证项目基本信息
        validateProjectConfig(config, errors);

        // 验证代码生成配置
        validateGenerationConfig(config, errors);

        // 如果有错误，抛出异常
        if (!errors.isEmpty()) {
            throw new ConfigurationException("配置验证失败：\n" + String.join("\n", errors));
        }
    }

    /**
     * 验证项目基本信息配置
     * 验证项目名称、版本号、包名等基本信息的完整性
     *
     * @param config 配置对象
     * @param errors 错误信息收集列表
     */
    private static void validateProjectConfig(Configuration config, List<String> errors) {
        if (config.getProject() == null) {
            errors.add("project 配置不能为空");
            return;
        }

        Configuration.ProjectConfig project = config.getProject();
        if (StringUtils.isBlank(project.getName())) {
            errors.add("project.name 不能为空");
        }
        if (StringUtils.isBlank(project.getVersion())) {
            errors.add("project.version 不能为空");
        }
        if (StringUtils.isBlank(project.getPackageName())) {
            errors.add("project.package 不能为空");
        }
    }

    /**
     * 验证代码生成配置
     * 验证模板路径、输出路径、数据库配置和模板配置的完整性
     *
     * @param config 配置对象
     * @param errors 错误信息收集列表
     */
    private static void validateGenerationConfig(Configuration config, List<String> errors) {
        if (config.getGeneration() == null) {
            errors.add("generation 配置不能为空");
            return;
        }

        Configuration.GenerationConfig generation = config.getGeneration();

        // 验证路径配置
        if (StringUtils.isBlank(generation.getTemplatePath())) {
            errors.add("generation.templatePath 不能为空");
        }
        if (StringUtils.isBlank(generation.getOutputPath())) {
            errors.add("generation.outputPath 不能为空");
        }

        // 验证数据库配置
        validateDatabaseConfig(generation.getDatabase(), errors);

        // 验证模板配置
        validateTemplatesConfig(generation.getTemplates(), errors);
    }

    /**
     * 验证数据库配置
     * 验证数据库类型、连接信息等配置的完整性
     *
     * @param database 数据库配置对象
     * @param errors 错误信息收集列表
     */
    private static void validateDatabaseConfig(Configuration.DatabaseConfig database, List<String> errors) {
        if (database == null) {
            errors.add("generation.database 配置不能为空");
            return;
        }

        // 验证数据库基本配置
        if (StringUtils.isBlank(database.getType())) {
            errors.add("generation.database.type 不能为空");
        }
        if (StringUtils.isBlank(database.getHost())) {
            errors.add("generation.database.host 不能为空");
        }
        if (database.getPort() <= 0) {
            errors.add("generation.database.port 必须大于0");
        }
        if (StringUtils.isBlank(database.getUsername())) {
            errors.add("generation.database.username 不能为空");
        }
        if (StringUtils.isBlank(database.getDatabase())) {
            errors.add("generation.database.database 不能为空");
        }
    }

    /**
     * 验证模板配置
     * 验证各类型模板的配置完整性，包括模板文件、输出路径和文件名格式
     *
     * @param templates 模板配置映射
     * @param errors 错误信息收集列表
     */
    private static void validateTemplatesConfig(java.util.Map<String, Configuration.TemplateConfig> templates, List<String> errors) {
        if (templates == null || templates.isEmpty()) {
            errors.add("generation.templates 配置不能为空");
            return;
        }

        // 验证每个模板的配置
        templates.forEach((key, template) -> {
            if (template == null) {
                errors.add("template [" + key + "] 配置不能为空");
                return;
            }

            // 验证模板必要属性
            if (StringUtils.isBlank(template.getTemplate())) {
                errors.add("template [" + key + "].template 不能为空");
            }
            if (StringUtils.isBlank(template.getOutputPath())) {
                errors.add("template [" + key + "].outputPath 不能为空");
            }
            if (StringUtils.isBlank(template.getFileNameFormat())) {
                errors.add("template [" + key + "].fileNameFormat 不能为空");
            }
        });
    }
}
